local VERSION = tonumber(("$Revision: 164 $"):match("%d+"))
AuldLangSyne = AceLibrary("AceAddon-2.0"):new("AceModuleCore-2.0", "AceEvent-2.0", "AceConsole-2.0", "AceDB-2.0")

local _G = getfenv(0)

AuldLangSyne.version = 'r'..VERSION
AuldLangSyne.revision = VERSION
AuldLangSyne.date = ("$Date: 2007-07-28 22:40:46 +0000 (Sat, 28 Jul 2007) $"):match("%d%d%d%d%-%d%d%-%d%d")

local new, del, newHash, newSet, deepCopy, deepDel, clear
do
	local list = setmetatable({}, {__mode='k'})
	function new(...)
		local t = next(list)
		if t then
			list[t] = nil
			for i = 1, select('#', ...) do
				t[i] = select(i, ...)
			end
			return t
		else
			return { ... }
		end
	end
	
	function newHash(...)
		local t = next(list)
		if t then
			list[t] = nil
		else
			t = {}
		end
		for i = 1, select('#', ...), 2 do
			t[select(i, ...)] = select(i+1, ...)
		end
		return t
	end
	
	function newSet(...)
		local t = next(list)
		if t then
			list[t] = nil
		else
			t = {}
		end
		for i = 1, select('#', ...) do
			t[select(i, ...)] = true
		end
		return t
	end
	
	function del(t)
		for k in pairs(t) do
			t[k] = nil
		end
		t[''] = true
		t[''] = nil
		list[t] = true
		return nil
	end
	
	function clear(t)
		for k in pairs(t) do
			t[k] = nil
		end
		t[''] = true
		t[''] = nil
		return t
	end
	
	function deepCopy(from)
		if type(from) ~= "table" then
			return from
		end
		local to = new()
		for k,v in pairs(from) do
			to[k] = deepCopy(v)
		end
		return to
	end

	function deepDel(t)
		if type(t) ~= "table" then
			return nil
		end
		for k,v in pairs(t) do
			t[k] = deepDel(v)
		end
		return del(t)
	end
end
AuldLangSyne.new = new
AuldLangSyne.del = del
AuldLangSyne.newHash = newHash
AuldLangSyne.newSet = newSet
AuldLangSyne.deepCopy = deepCopy
AuldLangSyne.deepDel = deepDel
AuldLangSyne.clear = clear

do
	local function get_Active(name)
		if AuldLangSyne:HasModule(name) then
			return AuldLangSyne:IsModuleActive(name)
		else
			return false
		end
	end
	local function set_Active(name, value)
		if not AuldLangSyne:HasModule(name) then
			local _,_,_,_,loadable = GetAddOnInfo("AuldLangSyne_" .. name) 
			if loadable then
				LoadAddOn("AuldLangSyne_" .. name)
			else
				return
			end
		end
		AuldLangSyne:ToggleModuleActive(name, value)
	end
	AuldLangSyne.menu = {
		type = "group",
		handler = AuldLangSyne,
		name = "AuldLangSyne",
		desc = "Options for AuldLangSyne.",
		args = {
			modules = {
				name = "Modules", type = "text",
				desc = "Modules",
				multiToggle = true,
				validate = {},
				validateDesc = {},
				get = get_Active,
				set = set_Active,
				order = 1,
				wfHidden = true,
			},
		},
	}
end

function AuldLangSyne:OnInitialize()
	self:RegisterDB("AuldLangSyneDB")
	
	local registeredWaterfall = false
	self:RegisterChatCommand({"/AuldLangSyne", "/auld", "/als"}, self.menu)
	self:RegisterChatCommand({"/alsconfig",}, function()
			if AceLibrary:HasInstance("Waterfall-1.0") then
				if not registeredWaterfall then
					registeredWaterfall = true
					AceLibrary("Waterfall-1.0"):Register("AuldLangSyne", 
						"aceOptions", self.menu,
						"title", "AuldLangSyne",
						"treeLevels", 5)
				end
				AceLibrary("Waterfall-1.0"):Open("AuldLangSyne")
			else
				self:Print("Waterfall-1.0 is required to access the GUI.")
			end
		end)
	
	--Stolen from AceDB.
	local _,race = UnitRace("player")
	if race == "Orc" or race == "Scourge" or race == "Troll" or race == "Tauren" or race == "BloodElf" then
		self.faction = "0"
	else
		self.faction = "1"
	end
end

local function InitializeExternalModules()
	for i = 1, GetNumAddOns() do
		local deps = newSet(GetAddOnDependencies(i))
		if deps["AuldLangSyne"] and IsAddOnLoadOnDemand(i) and not IsAddOnLoaded(i) then
			local name = GetAddOnInfo(i)
			if name:find("^AuldLangSyne_") then
				local modName = name:sub(14)
				local defaultState = tonumber(GetAddOnMetadata(name, "X-AuldLangSyne-DefaultState"))
				self:SetModuleDefaultState(modName, defaultState ~= 0)
				if self:IsModuleActive(modName, true) then
					local _,_,_,_,loadable = GetAddOnInfo(i)
					if loadable then
						LoadAddOn(i)
					end
				else
					self.options.args.modules.validate[modName] = modName
					self.options.args.modules.validateDesc[modName] = GetAddOnMetadata(name, "Notes")
				end
			end
		end
		deps = del(deps)
	end
end

function AuldLangSyne:OnEnable()
	InitializeExternalModules()
	self:RegisterEvent("ADDON_LOADED")
	self:ADDON_LOADED()
end

local pendingModules = {}
function AuldLangSyne:OnModuleCreated(name, module)
	self.menu.args.modules.validate[name] = name
	self.menu.args.modules.validateDesc[name] = ("Toggle whether the %s module is active"):format(name)
	pendingModules[name] = module
end

function AuldLangSyne:ADDON_LOADED()
	for name, module in pairs(pendingModules) do
		pendingModules[name] = nil
		if module.desc then
			self.menu.args.modules.validateDesc[name] = module.desc
		end
	end
end

function AuldLangSyne:OnModuleEnable(module)
	self.menu.args[string.lower(module.name)] = module.menu
end

function AuldLangSyne:OnModuleDisable(module)
	self.menu.args[string.lower(module.name)] = nil
end

